//////////////////
/// mkI - Base ///
//////////////////

// Base includes
#include "mkDebugWin.h"

namespace mk
{

void Trace
(
    char const* format,
    ...
)
{
    va_list argList;
    va_start( argList, format );
    char const* string = FormatOutputString( format, argList );
    TraceUnformatted( string );
    va_end( argList );
}

void TraceUnformatted
(
    char const* format,
    ...
)
{
    OutputDebugStringA( format );
    OutputDebugStringA( "\n" );
}

char const* FormatOutputString
(
    char const* format,
    ...
)
{
    va_list argList;
    va_start( argList, format );
    char const* result = FormatOutputString( format, argList );
    va_end( argList );
    return result;
}

char const* FormatOutputString
(
    char const* format,
    va_list     argList
)
{
    uint const max_chars = 4096;
    static char s_buffer[max_chars + 1];
    vsnprintf_s( s_buffer, max_chars, format, argList );
    // NIL-terminate.
    s_buffer[ max_chars ] = '\0';
    return s_buffer;
}

charW const* FormatOutputString
(
    charW const* format,
    ...
)
{
    va_list argList;
    va_start( argList, format );
    charW const* result = FormatOutputString( format, argList );
    va_end( argList );
    return result;
}

charW const* FormatOutputString
(
    charW const* format,
    va_list      argList
)
{
    uint const max_chars = 4096;
    static charW s_buffer[max_chars + 1];
    _vsnwprintf_s( s_buffer, max_chars, format, argList );
    // NIL-terminate.
    s_buffer[ max_chars ] = '\0';
    return s_buffer;
}

AssertResult Assert
(
    char  const* condition,
    char  const* function,
    char  const* filePath,
    uint  const  line,
    char  const* format,
    ...
)
{
    // Format the final message
    va_list args;
    va_start(args, format);
    char const* clientMessage = FormatOutputString(format, args);
    va_end(args);

    charW const* finalMessage = FormatOutputString( mkText("Message: %hs\r\nCondition: %hs\nFunction: %hs\nFile: %hs\nLine: %d\nAbort executable, Retry or Ignore?"), clientMessage, condition, function, __FILE__, __LINE__ );

    // Output the error to the console first
    OutputDebugStringW(mkText("\n----- mk Assert -------------------------------------\n"));
    OutputDebugStringW(finalMessage);
    OutputDebugStringW(mkText("\n-----------------------------------------------------\n"));

    int result = MessageBoxW( NULL, finalMessage, mkText("mk: Assert"), MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION );

    switch( result )
    {
        case IDIGNORE : return AssertResult_Ignore;
        case IDRETRY  : return AssertResult_Retry;
    }

    return AssertResult_Abort;
}

} // namespace mk

